<template>
  <table
    cellspacing="0"
    cellpadding="0"
    border="0"
    :style="{
      width: bodyWidth,
    }"
  >
    <colgroup>
      <col v-for="column in columns" :key="column.id" :name="column.id" />
      <col v-if="hasGutter" name="gutter" />
    </colgroup>
    <tbody :class="{ 'has-gutter': hasGutter }">
      <tr v-for="(row, rowIndex) in footerData" :key="rowIndex">
        <td
          v-for="(column, cellIndex) in columns"
          :key="column.id"
          :class="getRowClasses(column, cellIndex)"
          :rowspan="getSpan(row, column, rowIndex, cellIndex).rowspan"
          :colspan="getSpan(row, column, rowIndex, cellIndex).colspan"
          v-if="getSpan(row, column, rowIndex, cellIndex).colspan"
        >
          <render-cell
            :row="row"
            :column="column"
            :cellIndex="cellIndex"
            :cell="$parent.$scopedSlots[column.property]"
          ></render-cell>
        </td>
        <th v-if="hasGutter" class="gutter"></th>
      </tr>
    </tbody>
  </table>
</template>

<script>
import { Table } from "element-ui";
import LayoutObserver from "element-ui/packages/table/src/layout-observer";

export default {
  components: {
    RenderCell: {
      functional: true,
      render(
        h,
        {
          props: {
            row,
            column,
            column: { property, labelClassName },
            cellIndex,
            cell,
          },
        }
      ) {
        const cellValue = (row || [])[property] || "";
        const cellTag = "div";
        const cellProps = {
          class: [labelClassName],
          staticClass: "cell",
        };
        if (cell) {
          return h(cellTag, cellProps, [cell({ row })]);
        } else {
          return h(cellTag, cellProps, [cellValue]);
        }
      },
    },
  },
  props: {
    data: {
      type: Array,
      default: () => [],
    },
    fixed: String,
    summaryMethod: Function,
    summaryArray: Array,
  },
  destroyed() {
    this.tableLayout && this.tableLayout.removeObserver(this);
  },
  methods: {
    ...Table.components.TableBody.methods,
    ...LayoutObserver.methods,
    ...Table.components.TableFooter.methods,
    init() {
      this.tableLayout.addObserver(this);
    },
    getSummaries: function (param) {
      const { columns, data } = param;
      let propertySum = {};
      columns.forEach((column, index) => {
        if (index === 0) {
          propertySum[column.property] = "合计"; //重写合计栏数据
          return;
        }
        const values = data.map((item) => Number(item[column.property]));
        const precisions = [];
        let notNumber = true;//是否数字
        let isSummary = true;//是否需要计算
        if (this.summaryArray && this.summaryArray.length > 0) {
          isSummary = this.summaryArray.includes(column.property);
        }
        values.forEach((value) => {
          if (!isNaN(value)) {
            notNumber = false;
            let decimal = ("" + value).split(".")[1];
            precisions.push(decimal ? decimal.length : 0);
          }
        });
        const precision = Math.max.apply(null, precisions);
        if (!notNumber && isSummary) {
          propertySum[column.property] = values.reduce((prev, curr) => {
            const value = Number(curr);
            if (!isNaN(value)) {
              return parseFloat((prev + curr).toFixed(Math.min(precision, 20)));
            } else {
              return prev;
            }
          }, 0);
        } else {
          propertySum[column.property] = "";
        }
      });
      if (columns[0].property === "_section") {
        propertySum.spanOption = {
          [columns[0].property]: { rowspan: 1, colspan: 2 },
          [columns[1].property]: { rowspan: 0, colspan: 0 },
        };
      }
      return [propertySum]; //重写合计栏数据结构
    },
  },
  computed: {
    table() {
      return this.$parent.table;
    },
    columns() {
      return (this.table && this.table.store.states.columns) || [];
    },
    tableLayout() {
      return (this.table && this.table.layout) || {};
    },
    hasGutter() {
      return !this.fixed && this.tableLayout.gutterWidth;
    },
    bodyWidth() {
      return this.table && this.table.layout.bodyWidth + "px";
    },
    bodyWrapper() {
      return (this.table && this.table.bodyWrapper) || {};
    },
    footerData() {
      if (this.summaryMethod) {
        return (
          (this.table &&
            this.summaryMethod({
              columns: this.columns,
              data: this.table.store.states.data,
            })) ||
          []
        );
      }
      if (this.data && this.data.length) return this.data;
      return (
        this.table &&
        this.getSummaries({
          columns: this.columns,
          data: this.table.store.states.data,
        })
      );
    },
  },
};
</script>
